use <funnel.scad>;
use <screwLid.scad>; 

// variable "OBJECT2MAKE" controls what part of the filter funnel will be rendered:
//      1. funnel
//      2. lid
//      3. funnel counter screw
OBJECT2MAKE=2;

// funnel
funnelHeadLen=10;
funnelTransitionLen=10;
funnelPourerLen=10;
funnelDia=30;
funnelPourerDia=9;
funnelwallThick=2;
// ring used as stop so that funnel does cannot go through wall opening
ringStopOuterDia=funnelDia+(2*funnelwallThick)+2; // outer diameter of stop ring
ringStopInnerDia=funnelDia-(2*funnelwallThick);   // inner diameter of stop ring
ringStopHeight=funnelwallThick;                   // height of the stop ring 
// lid
lidDiameter=funnelDia;                            //od: Outer diameter of the thread 
caseWallThick=1;                                  //Thickness of the case walls the funnel is screwed on (=unthreaded section).
lidTopThick=funnelwallThick;                      //tt: Top thickness of top of screw lid
lidHeight=12+lidTopThick;                         //hg: The visible outside height of the lid that is portruding from case ( will be divided into screw lid and counter screw
counterScrewHeight=5;                             //The height of the screw used to fix the funnel in the case against the ringStop: screw lid will be 
lidTotalHeight=lidHeight+caseWallThick-lidTopThick;//tl: Total length of threaded section where lid is screwed on (tl = lt + unthreaded_length)
lidTolerance=0.5;                                 //    Tolerance between lid and jar threads
lidWall=funnelwallThick;                          //wt:  Wall thickness
lidBottom=0;                                      //bt:  Base thickness (may be zero) of jar ?
lidTop=0;                                         //tt:  Top thickness (may be zero) of jar ?
lidThreadHeight=3;                                //sth: Step height (the half will be used to countersink the ends)
lidThreadDegrees=55;                              //lf0: Step shape degrees.  Step, traveling length per turn
lidResolution=0.5;                                //rs:  Resolution -- set small values to minimize overhang issues (face at each 2mm of the perimeter)
lidThreadLen=lidTotalHeight;                      //lt:  Length of the threaded section of the screw.  Length (Z) of the tread; here *all* of the jar is threaded
lidCounterSink=2;                                 //cs:  Countersink in both ends
// holes in lid
MAKEFILTERHOLES=1;
holeDia=3;                                        // diameter of holes
holeDistance=1;                                   // distance holes are apart
holeNrSides=16;                                   // detail of holes: set this to 6 if you want a beehive pattern or to a higher value if you want rounder holes.

///////////////////////////////////////////////////////////////////////
if (OBJECT2MAKE==1)  // funnel
{
    echo("------> Rendering funnel part!");
    translate([0,0,lidTotalHeight])
    union()
    {
        ring(ringStopOuterDia,ringStopInnerDia,ringStopHeight);
        funnel( funnelDia, funnelHeadLen, funnelTransitionLen, funnelPourerDia, funnelPourerLen, funnelwallThick );
        rotate([0,180,0])
        hollowScrewThread( lidDiameter - lidTolerance*2,   //od:   Outer diameter of the thread
                            lidWall,            //wt:   wall thickness
                            lidBottom,          //bt:   base thickness (may be zero)
                            lidTop,             //tt:   top thickness (may be zero)
                            lidThreadHeight,    //sth:  Thread step 
                            lidThreadDegrees,   //lf0:  Step shape degrees.  Step, traveling length per turn
                            lidThreadLen,       //lt:   Length of the threaded section of the screw.  Length (Z) of the tread
                            lidTotalHeight,     //tl:   Total length of object (tl = lt + unthreaded_length)  
                            lidResolution,      //rs:   Resolution (face at each 2mm of the perimeter)
                            lidCounterSink      //cs:   Countersink in both ends
        );
    }
}
else if (OBJECT2MAKE==2)  // lid
{
    echo("------> Rendering screw lid!");
    cubeSideLen=lidDiameter+10;
    cubeHeight= lidHeight+10;
    if( MAKEFILTERHOLES==1)
    {
      difference()
      {
        difference()
        {
            screwLid(   lidDiameter,    //od: Outer diameter of the thread to match
                        lidWall,        //wt: wall_thickness. The thickness of the outer walls
                        lidTopThick,    //tt: top thickness
                        lidHeight,      //hg:  the height of the portruding threaded pipe + thickness of lid top
                        lidThreadHeight,//sth: Step height (the half will be used to countersink the ends)
                        lidThreadDegrees,//lf0: Degrees (same as used for the screw_thread example)
                        lidResolution   //rs: Resolution -- set small values to minimize overhang issues
            );
            translate([-cubeSideLen/2,-cubeSideLen/2,lidHeight-counterScrewHeight]) 
                cube(size=[cubeSideLen,cubeSideLen,cubeHeight], center=false);
        }
        //////////////////////////////////////////////////////////////////////////////////////////////
        roundRasterDia=lidDiameter-funnelwallThick;   // diameter of the round entire hole pattern
        roundRasterHeight=lidTopThick+1;            // cut the holes through the entire lid top
        roundRaster(holeDia, holeDistance, roundRasterDia, roundRasterHeight, holeNrSides);
      }
  }
  else
  {
    difference()
    {
        screwLid(   lidDiameter,    //od: Outer diameter of the thread to match
                    lidWall,        //wt: wall_thickness. The thickness of the outer walls
                    lidTopThick,    //tt: top thickness
                    lidHeight,      //hg:  the height of the portruding threaded pipe + thickness of lid top
                    lidThreadHeight,//sth: Step height (the half will be used to countersink the ends)
                    lidThreadDegrees,//lf0: Degrees (same as used for the screw_thread example)
                    lidResolution   //rs: Resolution -- set small values to minimize overhang issues
        );
        translate([-cubeSideLen/2,-cubeSideLen/2,lidHeight-counterScrewHeight]) 
            cube(size=[cubeSideLen,cubeSideLen,cubeHeight], center=false);
    }
  }

}
else if (OBJECT2MAKE==3)  // counter screw
{
    echo("------> Rendering counter screw!");
    cubeSideLen=lidDiameter+10;
    cubeHeight= lidHeight+10;
    translate([0,0,-(lidHeight-counterScrewHeight)])
    difference()
    {
    screwLid(   lidDiameter,    //od: Outer diameter of the thread to match
                lidWall,        //wt: wall_thickness. The thickness of the outer walls
                lidTopThick,    //tt: top thickness
                lidHeight,      //hg:  the height of the lid
                lidThreadHeight,//sth: Step height (the half will be used to countersink the ends)
                lidThreadDegrees,  //lf0: Degrees (same as used for the screw_thread example)
                lidResolution   //rs: Resolution -- set small values to minimize overhang issues
    );
    translate([-cubeSideLen/2,-cubeSideLen/2,-cubeHeight+lidHeight-counterScrewHeight]) 
            cube(size=[cubeSideLen,cubeSideLen,cubeHeight], center=false);
    }
}
else
{
    echo("------> Error: invalid value for variable OBJECT2MAKE: ", OBJECT2MAKE, "  !!!!!!");
}

////////////////////////////////////////////////////////////////////////
//
module ring( outerDia, innerDia, height )
{
    linear_extrude(height = height, $fn = 100) 
    {
        difference()
        {
            circle(d=outerDia);
            circle(d=innerDia);
        }
    }
}
/////////////////////////////////////////////////////////////////////////////////////
//
module roundRaster(cylinderDia, cylinderDistance, roundRasterDia, roundRasterHeight, fn)
{
    cylinderRad=cylinderDia/2.0;
    roundRasterRad=roundRasterDia/2.0;
    cylinderHeight=roundRasterHeight+1;
    yStepSize=cylinderDia+cylinderDistance;
    yNrSteps= roundRasterDia/yStepSize;
    // the distance between center of cylinders in x direction is determined by 
    // the height of an  equilateral triangle (sl = sidelen):
    // xStepSize = sqrt( sl^2 - (sl/2)^2 )
    xStepSize = sqrt( pow(yStepSize,2) - pow(yStepSize/2.0,2) );
    xNrSteps= roundRasterDia/xStepSize;
    
    translate([-roundRasterRad,-roundRasterRad,(roundRasterHeight/2.0)-0.5])
    intersection()
    {
        translate([roundRasterRad, roundRasterRad, 0]) 
            cylinder(h=roundRasterHeight, r=roundRasterRad, center=true);

        for ( xstep=[0:(xNrSteps/2.0)] )
        {
            translate([(2*xstep)*xStepSize, 0, 0])
            for ( ystep=[0:yNrSteps] )
            {
                translate([cylinderRad+cylinderDistance/2, ystep*yStepSize+cylinderRad+cylinderDistance/2, 0])
                cylinder(h=cylinderHeight, d=cylinderDia, center=true, $fn=fn);
            }
            translate([(2*xstep+1)*xStepSize, 0, 0])
            for ( ystep=[0:yNrSteps] )
            {
                translate([cylinderRad+cylinderDistance/2, ystep*yStepSize, 0])
                cylinder( h=cylinderHeight, d=cylinderDia, center=true, $fn=fn);
            }
        }
    }
}

